/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package negocio;

import java.util.*;
import javax.management.timer.Timer;
import persistencia.PersistenciaArticulo;
import persistencia.PersistenciaCliente;
import persistencia.PersistenciaPromocion;

/**
 * Clase que representa una promocion existente en el Videoclub
 * @author JAVA
 */
public class Promocion {

    private String descripcion;
    private float porcentaje;
    private int dias;
    private Date fechaInicio;
    private Date fechaFin;
    private Tipo t;
    String descripcionTipo;
    int id;

    /**
     * Crea una promocion con los datos necesarios
     * @param descripcion
     * @param porcentaje de descuento
     * @param dias extra 
     * @param fechaInicio
     * @param fechaFin de la promocion
     * @param Tipo de promocion
     * @param descripcion del tipo de la promocion Ej. si la promocion es de Genero el tipo podría ser Terror, Western...
     */
    public Promocion(String descripcion, float porcentaje, int dias, Date fechaInicio, Date fechaFin, Tipo t, String descripcionTipo) {
        this.descripcion = descripcion;
        this.porcentaje = porcentaje;
        this.dias = dias;
        this.fechaInicio = fechaInicio;
        this.fechaFin = fechaFin;
        this.t = t;
        this.descripcionTipo = descripcionTipo;

    }

    /**
     * Crea una promocion con los datos necesarios y el id ya que la crea a partir de una consulta en la BBDD
     * @param id
     * @param descripcion
     * @param porcentaje
     * @param dias
     * @param fechaInicio
     * @param fechaFin
     * @param Tipo de promocion 
     * @param descripcion del tipo de la promocion Ej. si la promocion es de Genero el tipo podría ser Terror, Western...
     */
    public Promocion(int id, String descripcion, float porcentaje, int dias, Date fechaInicio, Date fechaFin, Tipo t, String descripcionTipo) {
        this.descripcion = descripcion;
        this.porcentaje = porcentaje;
        this.dias = dias;
        this.fechaInicio = fechaInicio;
        this.fechaFin = fechaFin;
        this.t = t;
        this.descripcionTipo = descripcionTipo;
        this.id = id;
    }

    public int getId() {
        return id;
    }
    /**
     * 
     * @return un String con la descripcion del tipo de la promocion
     */
    public String getDescripcionTipo() {
        return descripcionTipo;
    }

    public void setDescripcionTipo(String descripcionTipo) {
        this.descripcionTipo = descripcionTipo;
    }

    public Date getFechaInicio() {
        return fechaInicio;
    }

    public void setFechaInicio(Date fechaInicio) {
        this.fechaInicio = fechaInicio;
    }
    /**
     * 
     * @return el tipo de promocion. Tipo es una clase enum
     */
    public Tipo getT() {
        return t;
    }
    /**
     * 
     * @param tipo de la promocion. Tipo es una clase enum
     */
    public void setT(Tipo t) {
        this.t = t;
    }

    public String getDescripcion() {
        return descripcion;
    }

    public void setDescripcion(String descripcion) {
        this.descripcion = descripcion;
    }

    public int getDias() {
        return dias;
    }

    public void setDias(int dias) {
        this.dias = dias;
    }

    public Date getFechaFin() {
        return fechaFin;
    }

    public void setFechaFin(Date fechaFin) {
        this.fechaFin = fechaFin;
    }
    /**
     * 
     * @return el porcentaje de descuento de la promocion
     */
    public float getPorcentaje() {
        return porcentaje;
    }
    /**
     * 
     * @param porcentaje de descuento a aplicar en la promocion
     */
    public void setPorcentaje(float porcentaje) {
        this.porcentaje = porcentaje;
    }
    /**
     * Verifica si la promocion es de Tipo Genero
     * @return true o false si la promocion es de Genero
     */
    public boolean esGenero() {
        if (t.equals(Tipo.Genero)) {
            return true;
        } else {
            return false;
        }
    }
    /**
     * 
     * @return true o false si la promocion es por Año
     */
    public boolean esAño() {
        if (t.equals(Tipo.Año)) {
            return true;
        } else {
            return false;
        }
    }
    /**
     * 
     * @return true or false si la promocion es por soporte. Ej. Play 1, Xbox...
     */
    public boolean esSoporte() {
        if (t.equals(Tipo.Soporte)) {
            return true;
        } else {
            return false;
        }
    }
    /**
     * 
     * @return true or false si la promocion es por Director
     */
    public boolean esDirector() {                                
        if (t.equals(Tipo.Director)) {
            return true;
        } else {
            return false;
        }
    }
    /**
     * 
     * @return true or false si la promocion es por un dia concreto
     */
    public boolean esDias() {
        if (t.equals(Tipo.Dias)) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public String toString() {

        return "\n --------------------- \n  ---- PROMOCION ----  \n --------------------- \n" + " Descripcion: " + descripcion + "\n Porcentaje: " + porcentaje + "\n dias: " + dias + "\n Fecha Inicio: " + fechaInicio + "\n Fecha Fin: " + fechaFin + "\n Tarifa: " + t + "\n Descripcion Tipo: " + descripcionTipo + "\n Id: " + id + "\n --------------------- \n";
    }
    
    /**
     * Recibe los datos de una promocion, crea un objeto promocion y lo manda a la Persistencia para que lo inserte en la BBDD
     * @param descripcion
     * @param porcentaje
     * @param dias
     * @param fechaInicio
     * @param fechaFin
     * @param tipo
     * @param descripcionTipo 
     */
    public static void addPromocion(Promocion p) throws Exception {
            if (persistencia.PersistenciaPromocion.insertarPromocion(p) != 1) {
                throw new ExcepcionPersistencia("Error al añadir la promocion");
            }
    }
    
    public static void informarPromociones() {
        List<Promocion> prom = PersistenciaPromocion.mostrarPromocionesVigentes();
        if(prom.isEmpty()){
            System.out.println("No hay promociones para informar");
        }
        List<Cliente> clientes = PersistenciaCliente.obtenerClientes();
        if (!prom.isEmpty()) {
            Iterator itC = clientes.iterator();
            Iterator itP = prom.iterator();
            String cadenaPromociones = "Video Club Cibernos os informa de las siguientes promociones en la actualidad";
            while (itP.hasNext()) {
                Promocion p = (Promocion) itP.next();
                cadenaPromociones += "\n\nPromocion " + p.getDescripcion();
                cadenaPromociones += "\nFecha de inicio: " + p.getFechaInicio().toString();
                cadenaPromociones += "\nFecha de fin: " + p.getFechaFin().toString();
                cadenaPromociones += "\nTipo de promocion: " + p.getT().toString();
                cadenaPromociones += "\nAplicable a: " + p.getDescripcionTipo();
                cadenaPromociones += "\nCon un porcentaje de descuento de: " + p.getPorcentaje() + "%";
                cadenaPromociones += "\nDias extra de alquiler: " + p.getDias();
            }
            cadenaPromociones += "\n\nAprovéchelas y acérquese por su videoclub de confianza";
            while (itC.hasNext()) {
                Cliente c = (Cliente) itC.next();
                String mail = c.getEmail();
                MailSender.send(mail, "Promociones actuales", false, cadenaPromociones);
                
            }
        }
        else{
            System.out.println("No hay promociones vigentes");
        }
    }
    
    /**
     * Recibe un codigo de la promocion y mediante una llamada a la persistencia lo elimina
     * @param codigo de la promocion a eliminar
     */
    public static void borrarPromocion(int codigo) throws ExcepcionPersistencia {
        if (PersistenciaPromocion.bajaPromocion(codigo) != 1) {
            throw new ExcepcionPersistencia("Error al eliminar la promocion");
        }
    }
    
    public static Promocion obtenerPromocion(int cod){
        Promocion p=PersistenciaPromocion.obtenerPromocion(cod);
        return p;
    }
    
    /**
     * Llama a la persistencia y recibe una lista con promociones y las muestra por pantalla
     * @return un entero con el numero de promociones existentes
     */
    public static int mostrarPromociones() {
        List<Promocion> prom = PersistenciaPromocion.mostrarPromociones();
        if(prom.isEmpty()){
            System.out.println("La lista de promociones esta vacia");
        }
        Iterator it = prom.iterator();
        System.out.println("---------------------------");
        System.out.println("Numero de promociones: " + prom.size());
        System.out.println("---------------------------");
        while (it.hasNext()) {
            Promocion p = (Promocion) it.next();
            System.out.println("Id: " + p.getId());
            System.out.println("Descripcion: " + p.getDescripcion() + " Porcentaje: " + p.getPorcentaje() + " Dias extra: " + p.getDias());
            System.out.println("Fecha de Inicio: " + p.getFechaInicio().toString());
            System.out.println("Fecha de fin: " + p.getFechaFin().toString());
            System.out.println("Tipo: " + p.getT().toString() + " Descripcion: " + p.getDescripcionTipo());
            System.out.println("---------------------------");
        }
        return prom.size();
    }
    
    /**
     * Recibe de la persistencia una lista de promociones actualmente inactivas
     * Recorre dicha lista para imprimir las promociones 
     * @return un entero con el tamaño de la lista de promociones
     */
    public static int mostrarPromocionesInactivas() {
        List<Promocion> prom = PersistenciaPromocion.mostrarPromocionesInactivas();
        if(prom.isEmpty()){
            System.out.println("La lista de promociones inactivas esta vacia");
        }
        Iterator it = prom.iterator();
        System.out.println("---------------------------");
        System.out.println("Numero de promociones: " + prom.size());
        System.out.println("---------------------------");
        while (it.hasNext()) {
            Promocion p = (Promocion) it.next();
            System.out.println("Id: " + p.getId());
            System.out.println("Descripcion: " + p.getDescripcion() + " Porcentaje: " + p.getPorcentaje() + " Dias extra: " + p.getDias());
            System.out.println("Fecha de Inicio: " + p.getFechaInicio().toString());
            System.out.println("Fecha de fin: " + p.getFechaFin().toString());
            System.out.println("Tipo: " + p.getT().toString() + " Descripcion: " + p.getDescripcionTipo());
            System.out.println("---------------------------");
        }
        return prom.size();
    }
    
    /**
     * Recibe un codigo de la promocion escogida para reactivarla y la pone de nuevo activa
     * @param codigo de la promocion a reactivar
     */
    public static void reactivarPromocion(int cod) throws ExcepcionPersistencia {

        if (PersistenciaPromocion.reactivarPromociones(cod) != 1) {
            throw new ExcepcionPersistencia("Error al reactivar la promocion");
        }
    }
    
    /**
     * Carga una lista de promociones de la persistencia cuya fecha de fin es inferior a la fecha actual
     * Recorre dicha lista y la muestra por pantalla
     * @return un entero con el numero de promociones en la lista
     */
    public static int mostrarPromocionesVigentes() {
        List<Promocion> prom = PersistenciaPromocion.mostrarPromocionesVigentes();
        if (prom.isEmpty()){
            System.out.println("La lista de promociones vigentes esta vacia");
        }
        Iterator it = prom.iterator();
        System.out.println("---------------------------");
        System.out.println("Numero de promociones: " + prom.size());
        System.out.println("---------------------------");
        while (it.hasNext()) {
            Promocion p = (Promocion) it.next();
            System.out.println("Id: " + p.getId());
            System.out.println("Descripcion: " + p.getDescripcion() + " Porcentaje: " + p.getPorcentaje() + " Dias extra: " + p.getDias());
            System.out.println("Fecha de Inicio: " + p.getFechaInicio().toString());
            System.out.println("Fecha de fin: " + p.getFechaFin().toString());
            System.out.println("Tipo: " + p.getT().toString() + " Descripcion: " + p.getDescripcionTipo());
            System.out.println("---------------------------");
        }
        return prom.size();
    }
    
    
    /**
     * Recibe los datoss necesarios y los manda a la Persistencia
     * @param codigo de la promocion a modificar
     * @param nombre del campo a modificar
     * @param nuevo valor a insertar en la tarifa
     */
    public void actualizarPromocion(){

        if(PersistenciaPromocion.modificarPromocion(this)==1){
            System.out.println("Promocion modificada correctamente");
        }
        else{
            System.out.println("Error al modificar la promocion");
        }
    }
    
    /**
     * Aplica tanto el porcentaje de descuento como los dias extra asociados a la promocion a aplicar
     * @param Alquiler sobre el cual se aplica la promocion
     * @param promocion a aplicar sobre el alquiler
     */
    public static void aplicacionPromocion(ArticuloAlquilado aa, Promocion promo) {
        //Comprueba si la fecha Fin Alquiler coincide con los dias de la Promocion, si no modifica la fecha Fin Alquiler
        if (promo.getDias() != 0) {
            Date fechaActual = aa.getFechaEntrega();
            long fecha = fechaActual.getTime() + (promo.getDias()) * Timer.ONE_DAY;
            Date nuevaFecha = new Date(fecha);
            aa.setFechaEntrega(nuevaFecha);
        }
        //Comprueba si porcentaje de Promocion es > 0, y modifica el Precio de Alquiler
        if (promo.getPorcentaje() != 0) {
            float precio = aa.getPrecio();
            aa.setPrecio(precio - (precio * (promo.getPorcentaje() / 100)));
        }

    }

    /**
     * Carga una lista de promociones a traves de la Persistencia de Promociones
     * Para cada articulo de la lista de alquileres recorre la lista de promociones revisando si el articulo
     * cumple los requisitos de la promocion.
     * Si los cumple llama al método aplicacionPromocion pasandole el alquiler y la promocion
     * Ademas añade la promocion a una lista de promociones del alquiler para su impresión en una posterior factura
     * @param lista de alquileres sobre la cual comprobar si cumple algunas de las promociones existentes
     */
    public static void comprobarPromociones(List<ArticuloAlquilado> lista) {
        List<Promocion> listaPromociones = PersistenciaPromocion.mostrarPromocionesVigentes();
        for (ArticuloAlquilado aa : lista) {
            Articulo a=PersistenciaArticulo.obtenerArticulo(aa.getId());
            if (a instanceof Pelicula) {
                Pelicula peli = (Pelicula) a;
                for (Promocion promo : listaPromociones) {
                    if (promo.esAño() && peli.getAnyo() == Integer.parseInt(promo.getDescripcionTipo())) {
                        aa.getListap().add(promo);
                        aplicacionPromocion(aa, promo);
                    }
                    if (promo.esDirector() && peli.getDirector().compareTo(promo.getDescripcionTipo()) == 0) {
                        aa.getListap().add(promo);
                        aplicacionPromocion(aa, promo);
                    }
                    if (promo.esGenero() && peli.getGenero().compareTo(promo.getDescripcionTipo()) == 0) {
                        aa.getListap().add(promo);
                        aplicacionPromocion(aa, promo);
                    }
                    if (promo.esDias() && Calendar.getInstance().getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.getDefault()).compareToIgnoreCase(promo.getDescripcionTipo()) == 0) {
                        aa.getListap().add(promo);
                        aplicacionPromocion(aa, promo);
                    }

                }
            }
            if (a instanceof Juego) {
                Juego juego = (Juego) a;
                for (Promocion promo : listaPromociones) {
                    if (promo.esGenero() && juego.getGenero().compareTo(promo.getDescripcionTipo()) == 0) {
                        aa.getListap().add(promo);
                        aplicacionPromocion(aa, promo);
                    }
                    if (promo.esSoporte() && juego.getSoporte().compareTo(promo.getDescripcionTipo()) == 0) {
                        aa.getListap().add(promo);
                        aplicacionPromocion(aa, promo);
                    }
                    if (promo.esDias() && Calendar.getInstance().getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.getDefault()).compareToIgnoreCase(promo.getDescripcionTipo()) == 0) {
                        aa.getListap().add(promo);
                        aplicacionPromocion(aa, promo);
                    }
                }
            }
        }
    }
    
}
